package prome

import (
	prometheus2 "github.com/prometheus/client_golang/prometheus"
	"gorm.io/gorm"
	"time"
)

type Callback struct {
	summary *prometheus2.SummaryVec
}

func (Callback) Name() string {
	return ""
}
func (c Callback) Initialize(db *gorm.DB) error {
	db.Callback().Create().Before("*").Register("prometheus_create_before", c.before())
	db.Callback().Create().After("*").Register("prometheus_create_after", c.after("create"))
	db.Callback().Update().Before("*").Register("prometheus_update_before", c.before())
	db.Callback().Update().After("*").Register("prometheus_update_after", c.after("update"))
	db.Callback().Delete().Before("*").Register("prometheus_delete_before", c.before())
	db.Callback().Delete().After("*").Register("prometheus_delete_after", c.after("delete"))
	db.Callback().Query().Before("*").Register("prometheus_query_before", c.before())
	db.Callback().Query().After("*").Register("prometheus_query_after", c.after("query"))
	prometheus2.MustRegister(c.summary)
	return nil
}

func NewCallback(Namespace, Subsystem, Name, Help, InstanceID string) *Callback {
	labels := []string{"type", "table"}
	summary := prometheus2.NewSummaryVec(prometheus2.SummaryOpts{ //摘要
		Namespace: Namespace,
		Subsystem: Subsystem,
		Name:      Name,
		Help:      Help,
		ConstLabels: map[string]string{
			"db":          "webook",
			"idstance_id": InstanceID,
		},
		Objectives: map[float64]float64{
			0.5:   0.01,
			0.9:   0.05,
			0.99:  0.001,
			0.999: 0.0001,
		},
	}, labels)
	return &Callback{
		summary: summary,
	}
}
func (c *Callback) before() func(db *gorm.DB) {
	return func(db *gorm.DB) {
		startTime := time.Now()
		db.Set("start", startTime)
	}
}
func (c *Callback) after(typ string) func(db *gorm.DB) {
	return func(db *gorm.DB) {
		val, _ := db.Get("start")
		startTime, _ := val.(time.Time)
		dura := time.Since(startTime)

		table := db.Statement.Table
		if table == "" {
			table = "unknow"
		}
		c.summary.WithLabelValues(typ, table).Observe(float64(dura.Milliseconds()))
	}
}
